package com.ljg.activiti.l_grouptask;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngines;
import org.activiti.engine.history.HistoricIdentityLink;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 指定组任务办理人的三种方式
 * 
 * 1、在bpmn文件中的任务节点的属性中，选择Main Config 选项卡的candidateUsers属性设置办理人，硬编码的方式，直接指定 小A,小B,小C,小D
 * 
 * 2、在bpmn文件中的任务节点的属性中，选择Main Config 选项卡的candidateUsers属性设置办理人，使用流程变量 #{userIds} 或者 ${userIds}的形式指定
 * 
 * 3、在bpmn文件中的任务节点的属性中，选择 Listeners 选项卡，添加一个监听器，这个类实现了TaskListener接口，其中notify()用来指定任务的办理人
 * 
 * @author guo
 *
 */
public class GroupTaskTest {

	private Logger log = LoggerFactory.getLogger(GroupTaskTest.class);
	
	// 流程引擎对象
	private ProcessEngine processEngine;
	
	@Before
	public void before() {
		/**
		 * 创建默认的流程引擎对象，默认读取classpath下的activiti.cfg.xml创建流程引擎对象
		 */
		processEngine = ProcessEngines.getDefaultProcessEngine();
		log.info("创建流程引擎对象成功！");
	}
	
	/**
	 * 部署流程定义-从inputstream
	 *  processEngine.getRepositoryService()：获取流程定义和流程部署相关的Service
	 */
	@Test
	public void deploymentProcessDefinition_inputstream() {
		InputStream bpmnIn = this.getClass().getClassLoader().getResourceAsStream("diagrams/GroupTaskProcess.bpmn");
		InputStream pngIn = this.getClass().getClassLoader().getResourceAsStream("diagrams/GroupTaskProcess.png");
		Deployment deployment = processEngine.getRepositoryService() // 获取流程定义和流程部署相关的Service
			.createDeployment() // 创建流程部署对象
			.addInputStream("GroupTaskProcess.bpmn", bpmnIn) // 从InputStream中加载流程资源
			.addInputStream("GroupTaskProcess.png", pngIn) // 
			.name("组任务分配测试流程") // 添加部署的名称
			.deploy();
		
		log.info("部署完成，deploymentId=" + deployment.getId() + "，deploymentName=" + deployment.getName() + "，deploymentTime=" + deployment.getDeploymentTime());
	}
	
	/**
	 * 启动流程实例
	 * processEngine.getRuntimeService() // 获得正在执行的流程实例和执行对象相关的Service
	 */
	@Test
	public void startProcessInstance() {
		String processDefinitionKey = "GroupTaskProcess"; // 流程定义的key对应bpmn文件中id的属性值
		Map<String, Object> variables = new HashMap<>();
		variables.put("userIds", "大大,中中,小小");
		
		// 启动流程的时候，使用流程变量，指定任务的办理人
		ProcessInstance processInstance = processEngine.getRuntimeService() // 获得与正在执行的流程实例和执行对象相关的Service
			.startProcessInstanceByKey(processDefinitionKey, variables); // 根据流程定义的key启动流程实例，默认是按照最新版本的流程定义启动
		log.info("启动流程成功，Id=" + processInstance.getId() + "，deploymentId=" + processInstance.getDeploymentId() + "，name=" + processInstance.getName() + "，processInstanceId=" + processInstance.getProcessInstanceId());
	}
	
	/**
	 * 查询当前人的个人任务
	 * 
	 * processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
	 */
	@Test
	public void findMypersonalTask() {
		String assignee = "小A"; // 小A,小B,小C,小D
		List<Task> taskList = processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
			.createTaskQuery() // 创建任务查询对象
			.taskAssignee(assignee) // 指定任务办理人
			.list(); // 完成查询
		
		if(null == taskList || taskList.size() == 0) {
			log.error("没有查询到" + assignee + "的个人任务！");
			return;
		}
		
		for(Task task : taskList) {
			log.info("任务Id=" + task.getId() + "，任务名称=" + task.getName() + "，任务创建时间=" + task.getCreateTime() + "，流程实例Id=" + task.getProcessInstanceId() + "，执行的对象Id=" + task.getExecutionId() + "，流程定义Id=" + task.getProcessDefinitionId());
		}
	}
	
	/**
	 * 查询组任务
	 * 
	 * processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
	 */
	@Test
	public void findGroupTask() {
		String candidateUser = "小A"; // 小A,小B,小C,小D
		List<Task> taskList = processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
			.createTaskQuery() // 创建任务查询对象
			.taskCandidateUser(candidateUser) // 查询组任务
			.list(); // 完成查询
		
		if(null == taskList || taskList.size() == 0) {
			log.error("没有查询到" + candidateUser + "的组任务！");
			return;
		}
		
		for(Task task : taskList) {
			log.info("任务Id=" + task.getId() + "，任务名称=" + task.getName() + "，任务创建时间=" + task.getCreateTime() + "，流程实例Id=" + task.getProcessInstanceId() + "，执行的对象Id=" + task.getExecutionId() + "，流程定义Id=" + task.getProcessDefinitionId());
		}
	}
	
	/**
	 * 完成我的任务
	 * processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
	 */
	@Test
	public void completeMyPersonalTask() {
		String taskId = "175005";
		processEngine.getTaskService() // 获得与正在执行的任务管理相关的Service
			.complete(taskId);
		log.info("完成任务：任务Id=" + taskId);
	}
	
	/**
	 * 可以分配个人任务从一个人到另一个人（认领任务，改变任务的办理人，改派）
	 */
	@Test
	public void setAssigneeTask() {
		String taskId = "142504"; // 任务Id
		String assignee = "张无忌"; // 任务的办理人
		processEngine.getTaskService() // 获得正在执行的任务相关Service
			.setAssignee(taskId, assignee);
		
		log.info("改变任务办理人成功！");
	}
	
	/**
	 * 查询正在执行的任务办理人表
	 */
	@Test
	public void findRunPersonTask() {
		String taskId = "155004"; // 任务Id
		List<IdentityLink> identityLinksForTask = processEngine.getTaskService() //
			.getIdentityLinksForTask(taskId); // 根据任务Id查询
		
		if(null == identityLinksForTask || identityLinksForTask.size() == 0) {
			log.error("没有查询到" + taskId + "的组任务办理人！");
			return;
		}
		
		for(IdentityLink link : identityLinksForTask) {
			log.info(link.getTaskId() + "---" + link.getUserId() + "---" + link.getType() + "---" + link.getProcessInstanceId());
		}
		
	}
	
	/**
	 * 查询历史的任务办理人表
	 */
	@Test
	public void findHistoryTask() {
		String processInstanceId = "155001"; // 流程实例查询
		List<HistoricIdentityLink> historicIdentityLinksForProcessInstance = processEngine.getHistoryService() //
			.getHistoricIdentityLinksForProcessInstance(processInstanceId);
		
		if(null == historicIdentityLinksForProcessInstance || historicIdentityLinksForProcessInstance.size() == 0) {
			log.error("没有查询到" + processInstanceId + "的组任务办理人！");
			return;
		}
		
		for(HistoricIdentityLink link : historicIdentityLinksForProcessInstance) {
			log.info(link.getProcessInstanceId() + "---" + link.getTaskId() + "---" + link.getUserId() + "---" + link.getType());
		}
		
	}
	
	/**
	 * 拾取任务，将组任务分配给个人任务，指定任务的办理人字段
	 */
	@Test
	public void claim() {
		String taskId = "175005"; // 正在执行的任务Id
		String userId = "大大"; // 分配的个人任务，（可以是组任务中的成员，也可以是非组任务的成员）
		processEngine.getTaskService() //
			.claim(taskId, userId);
		log.info("分配成功！");
	}
	
	/**
	 * 将个人任务回退到组任务，前提，之前一定是组任务
	 */
	@Test
	public void setAssignee() {
		String taskId = "155004"; // 正在执行的任务Id
		processEngine.getTaskService() // 
			.setAssignee(taskId, null);
		
		log.info("设置成功！");
	}
	
	/**
	 * 向组任务中添加成员
	 */
	@Test
	public void addGroupUser() {
		String taskId = "155004"; // 正在执行的任务Id
		String userId = "大H"; // 成员办理人
		processEngine.getTaskService() // 
			.addCandidateUser(taskId, userId);
		
		log.info("设置成功！");
	}
	
	/**
	 * 从组任务中删除成员
	 */
	@Test
	public void deleteGroupUser() {
		String taskId = "155004"; // 正在执行的任务Id
		String userId = "小B"; // 成员办理人
		processEngine.getTaskService() // 
			.deleteCandidateUser(taskId, userId);
		
		log.info("设置成功！");
	}
	
}
